﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using FBGraph.Core.Text;
using System.Collections.Generic;

namespace FBGraph.Models
{
    internal class PageConverter : JsonConverter
    {
        internal static readonly Dictionary<String, PropertyInfo> PageProperties = GetPropertyData();

        internal static Dictionary<String, PropertyInfo> GetPropertyData()
        {
            return (
                from prop in typeof(Page).GetProperties()
                select new
                {
                    Info = prop,
                    PropertyAttr = (JsonPropertyAttribute)prop.GetCustomAttributes(typeof(JsonPropertyAttribute), true).SingleOrDefault()
                }).ToDictionary(p => p.PropertyAttr == null ? p.Info.Name : p.PropertyAttr.PropertyName, p => p.Info);
        }

        public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override Boolean CanWrite { get { return false; } }

        public override Object ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
        {
            if (existingValue == null) existingValue = new Page();

            while (reader.Read())
            {
                switch (reader.TokenType)
                {
                    case JsonToken.PropertyName:

                        var propertyName = (String)reader.Value;
                        if (reader.Read())
                        {
                            if (PageProperties.ContainsKey(propertyName))
                            {
                                var propertyInfo = PageProperties[propertyName];
                                var propertyValue = serializer.Deserialize(reader, propertyInfo.PropertyType);

                                propertyInfo.SetValue(existingValue, propertyValue, null);
                            }
                            else
                            {
                                var propertyValue = serializer.Deserialize(reader);
                                ((Page)existingValue).Details.Add(propertyName, propertyValue == null ? (String)null : propertyValue.ToString());
                            }
                        }
                        break;

                    case JsonToken.EndObject:
                        return existingValue;
                }
            }

            return existingValue;
        }

        public override Boolean CanConvert(Type objectType)
        {
            return
                objectType == typeof(Page) ||
                objectType.IsSubclassOf(typeof(Page));
        }
    }
}